Skip to content

Faster GIF animation decoding - #70

Merged
matmen merged 1 commit into
masterfrom
faster-gif-decode
Oct 16, 2026
Merged

matmen merged 1 commit into
masterfrom
faster-gif-decode

Conversation

@matmen

@matmen matmen commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Decoding animated GIFs was the other operation where a pure-JS library beat us: omggif took 123 ms for the benchmark's 101-frame GIF, we took 134 ms.

Before, every frame was copied several times:

  1. Decoding wrote each frame out as RGBA.
  2. Compositing read that RGBA back, checked every pixel's alpha byte and copied the canvas.
  3. Frame copied the result once more into a freshly zeroed bitmap.

Changes

  • Decoded frames keep their color indices (in display order, de-interlaced) and a 256-entry table of their colors.
  • Compositing writes the colors straight onto the canvas and skips the transparent index.
  • Frames take the composited copies as their bitmaps instead of copying them. The WebP and APNG composites already produce a fresh copy per frame as well.

Results

ms
before 134
this PR 83
omggif 123
gifuct-js 196

The output is bit-identical: decoding plus GIF/APNG re-encoding of the decoded frames was checked against master on 1593 corpus images (1970 results, 0 different).

The changelog entry goes under 3.2.1, which #68 adds as well (trivial conflict).

🤖 Generated with Claude Code

https://claude.ai/code/session_01YJgRK5qpwJEbHPuFv6kgAQ

Decoding wrote every frame as RGBA, compositing read it back (checking
each pixel's alpha byte) and copied the canvas, and the Frame copied it
once more into a zeroed bitmap. Frames now keep their indices (in display
order) and a table of their colors: compositing writes the colors
straight onto the canvas, skipping the transparent index, and the frames
take the composited copies as their bitmaps.

The benchmark's 101 frame GIF decodes in 83 instead of 134 ms (omggif:
123 ms). Bit-identical: decoding and re-encoding checked against master
on 1593 images.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJgRK5qpwJEbHPuFv6kgAQ
@matmen
matmen force-pushed the faster-gif-decode branch from 6ee695e to 8c0a821 Compare October 16, 2026 09:51
@matmen
matmen merged commit 80100ca into master Oct 16, 2026
13 checks passed
@matmen
matmen deleted the faster-gif-decode branch October 16, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant